﻿#include "guild_brief_logic.h"

#include <vector>
#include <string>

#include "guild/module/guild_module_loader.hpp"

#include "AnnounceMsg_struct.h"
#include "AnnounceData_struct.h"
#include "GuildModuleBrief_struct.h"

#include "error/make_error_code.h"
#include "guild_service_basic.h"
#include "guild/module/guild_module.h"


namespace guild_service {

bool GuildBriefLogic::GetGuildModuleBrief(const guild_id_type guild_id,
                            GuildModuleBrief &module_brief) {
  return detail::GetGuildModule<GuildModuleBrief>(kGuildServiceBasicName, guild_id,
                                              kGuildModuleBriefName, module_brief);
}

bool GuildBriefLogic::GetGuildModuleBriefByRole(const role_uuid_type role_uuid,
                                          GuildModuleBrief& module_brief) {
  if (role_uuid == kInvalidRoleUuid) {
    return false;
  }
  guild_id_type guild_id =
      GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    return false;
  }
  return GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief);
}

const std::string& GuildBriefLogic::GetGuildName(const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    static std::string sEmptyString;
    return sEmptyString;
  }
  return module_brief.name;
}

uint32_t GuildBriefLogic::GetGuildLevel(const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return 0;
  }
  return module_brief.level;
}

guild_icon_id_type GuildBriefLogic::GetGuildIconId(
    const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return 0;
  }
  return module_brief.icon;
}

const std::string& GuildBriefLogic::GetGuildDeclaration(
    const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    static std::string sEmptyString;
    return sEmptyString;
  }
  return module_brief.declaration;
}

const std::string& GuildBriefLogic::GetGuildAnnounce(
    const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    static std::string sEmptyString;
    return sEmptyString;
  }

  return module_brief.announce;
}

const role_uuid_type GuildBriefLogic::GetCreatorUuid(
    const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return kInvalidRoleUuid;
  }
  return module_brief.creator_uuid;
}

const role_uuid_type GuildBriefLogic::GetChairmanUuid(
    const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return kInvalidRoleUuid;
  }
  return module_brief.chairman_uuid;
}

const role_uuid_type GuildBriefLogic::GetViceChairmanUuid(
    const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return kInvalidRoleUuid;
  }
  return module_brief.vice_chairman_uuid;
}

bool GuildBriefLogic::IsAutoApproval(const guild_id_type guild_id) {
  static GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return false;
  }
  return module_brief.is_auto_approval;
}

bool GuildBriefLogic::SetAutoApproval(const role_uuid_type role_uuid,
                                      const bool is_auto_approval,
                                      error_code& ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_LOAD_FAILED;
    return false;
  }

  module_brief.is_auto_approval = is_auto_approval;

  if (!detail::SaveGuildModule<GuildModuleBrief>(
          kGuildServiceBasicName, module_brief, guild_id, kGuildModuleBriefName)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildBriefLogic::AddNews(const guild_id_type guild_id,
                              const GuildBriefLogic::NewsType& news) {
  if (guild_id == kInvalidGuildId) {
    return false;
  }
  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return false;
  }

  // TODO
  std::size_t max_count = 10;
  auto& news_list = module_brief.news_list;

  while (!news_list.empty() && news_list.size() >= max_count) {
    news_list.pop_back();
  }
  // TODO An iterator that points to the inserted data.
  // This function will insert a copy of the given value before the specified
  // location. Note that this kind of operation could be expensive for a %vector
  // and if it is frequently used the user should consider using std::list.
  // news_list.insert(news_list.begin(), news);
  news_list.emplace_back(news);

  // TODO

  return true;
}

void GuildBriefLogic::ForeachNews(
    const guild_id_type guild_id,
    const GuildBriefLogic::ForeachNewsCallbackType& callback) {
  if (!callback) {
    return;
  }

  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    return;
  }

  for (const auto& it : module_brief.news_list) {
    callback(it);
  }
}

bool GuildBriefLogic::ChangeGuildIconIdByRole(const role_uuid_type role_uuid,
                                              const guild_icon_id_type icon_id,
                                              error_code& ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_LOAD_FAILED;
    return false;
  }

  module_brief.icon = icon_id;

  if (!detail::SaveGuildModule<GuildModuleBrief>(
          kGuildServiceBasicName, module_brief, guild_id, kGuildModuleBriefName)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildBriefLogic::ChangeGuildNameByRole(const role_uuid_type role_uuid,
                                            const std::string& name,
                                            error_code& ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }
  
  if (GuildServiceBasicSingleton->IsGuildNameExisted(name)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_NAME_EXIST;
    // LOG_DEBUG("公会名字已存在 公会:%s 名字:%s", DumpGuild(guild).c_str(),
    return false;
  }

  guild_id_type guild_id = GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_LOAD_FAILED;
    return false;
  }

  module_brief.name = name;

  if (!detail::SaveGuildModule<GuildModuleBrief>(
          kGuildServiceBasicName, module_brief, guild_id, kGuildModuleBriefName)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildBriefLogic::ChangeGuildDeclarationByRole(
    const role_uuid_type role_uuid, const std::string& declaraion,
    error_code& ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_LOAD_FAILED;
    return false;
  }

  module_brief.declaration = declaraion;

  if (!detail::SaveGuildModule<GuildModuleBrief>(
          kGuildServiceBasicName, module_brief, guild_id, kGuildModuleBriefName)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildBriefLogic::ChangeGuildAnnounceByRole(const role_uuid_type role_uuid,
                                                const std::string& announce,
                                                error_code& ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  guild_id_type guild_id = GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_LOAD_FAILED;
    return false;
  }

  module_brief.announce = announce;

  if (!detail::SaveGuildModule<GuildModuleBrief>(
          kGuildServiceBasicName, module_brief, guild_id, kGuildModuleBriefName)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildBriefLogic::GiveGuildItem(const role_uuid_type role_uuid,
                            const uint32_t item_id, const uint32_t item_count,
                            error_code &ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  if (item_count == 0) {
    ec = ErrorCode::ERR_GUILD_BRIEF_GIVE_ITEM_NUM_INVALID;
    return false;
  }

  if (item_id != 101 || item_id != 102) {
    ec = ErrorCode::ERR_GUILD_BRIEF_GIVE_ITEM_ID_INVALID;
    return false;
  }

  // TODO -> cost item call

  guild_id_type guild_id = GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }
  
  GuildModuleBrief module_brief;
  if (!GuildBriefLogic::GetGuildModuleBrief(guild_id, module_brief)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_LOAD_FAILED;
    return false;
  }

  uint64_t exchange = 100;
  uint64_t add_money = exchange * item_count;
  module_brief.today_money += add_money;

  if (!detail::SaveGuildModule<GuildModuleBrief>(
          kGuildServiceBasicName, module_brief, guild_id, kGuildModuleBriefName)) {
    ec = ErrorCode::ERR_GUILD_BRIEF_SAVE_FAILED;
    return false;
  }

  return true;
}

}  // namespace guild_service